
package net.mattjoyce.buzzwordbingo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;


public class MainScreen extends Activity implements OnClickListener {
    
	private static final int GREEN_INT = 0xff00ff00;		//for TextViews
    private static final String TAG = "BuzzWordBingo";

    private GridView mGrid;
    private TextView statustv;
    public boolean gameisrunning = false;
    public String[] default_phrases;
    public String[] phrases;
    private boolean[] matched;
    public myAdapter mAdapter;
    private Button StartStopButton;
    private Button statusButton;
    SharedPreferences mPrefs;
    private SpeechRecognizer sr;
    Intent srintent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // window features - must be set prior to calling setContentView...
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // Inflate UI from its XML layout.
        setContentView(R.layout.main_screen);

        StartStopButton = (Button) findViewById(R.id.btn_startstop);
        statusButton = (Button) findViewById(R.id.listenStatusButton);
        statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.bluebuttonround));
        statustv = (TextView) findViewById(R.id.statustv);
        mGrid = (GridView) findViewById(R.id.maingrid);
     }
    
    @Override
	protected void onPause() {
		super.onPause();
		//TODO: COMMIT PREFERENCES
		
		stopgame();
		sr.cancel();
		sr.destroy();
		sr = null;
	}

	@Override
	protected void onResume() {
		super.onResume();

		// Check to see if a recognition activity is present
        PackageManager pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(srintent, 0);
        if (activities.size() != 0) {
            StartStopButton.setOnClickListener(this);
        } else {
            StartStopButton.setEnabled(false);
            StartStopButton.setText("Error..");
            statustv.setText(getResources().getString(R.string.no_speech_recognizer));
        }
        pm = null;

     	mPrefs=PreferenceManager.getDefaultSharedPreferences(this);
     	
     	loadPrefs();

        mAdapter = new myAdapter(this);
        mGrid.setAdapter(mAdapter);

        sr = SpeechRecognizer.createSpeechRecognizer(this);       
        sr.setRecognitionListener(new listener());
        srintent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
     	srintent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-GB");
     	srintent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,"net.mattjoyce.buzzwordbingo");
	}

	class listener implements RecognitionListener {
    	public void onReadyForSpeech(Bundle params) {
    		Log.d(TAG, "onReadyForSpeech");
    		statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.greenbuttonround));
    		statustv.setText("Idle/Listening for speech....");
    	}
    	public void onBeginningOfSpeech() {
    		Log.d(TAG, "onBeginningOfSpeech");
    		statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.yellowbuttonround));
    		statustv.setText("Speech heard! Waiting for end..");
    	}
    	public void onRmsChanged(float rmsdB) {
    		//Log.d(TAG, "onRmsChanged");
    	}
    	public void onBufferReceived(byte[] buffer) {
    			//Log.d(TAG, "onBufferReceived");
    	}
    	public void onEndOfSpeech() {
    		Log.d(TAG, "onEndofSpeech");
    		if (gameisrunning) {
    			statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.redbuttonround));
    			statustv.setText("Please wait, processing speech, not listening...");
    		}
    	}
    	public void onError(int error) {
    		
    		String errorstr="";
    		switch (error) {
    		case SpeechRecognizer.ERROR_NO_MATCH:
    			errorstr="NO MATCH";
    			break;
    		case SpeechRecognizer.ERROR_CLIENT:
    			errorstr="Client Error";
    			break;
    		case SpeechRecognizer.ERROR_AUDIO:
    			errorstr="Audio Recording Error";
    			break;
    		case SpeechRecognizer.ERROR_NETWORK_TIMEOUT :
    			errorstr="Network Operation Timed Out";
    			break;
    		case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
    			errorstr="Recognition Service Busy";
    			break;
    		case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
    			errorstr="No Speech Input (TimeOut)";
    			break;
    		case SpeechRecognizer.ERROR_SERVER:
    			errorstr="Server Error returned";
    			break;
    		default:
    			errorstr="Unhandled ErrorCode: " +  error;
    		}
    		Log.d(TAG, "SpeechRecognizer: Error int: " + error + " - String: " + errorstr);
    		sr.cancel();

    		if (gameisrunning) {
    			statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.redbuttonround));
    			statustv.setText("Error: " + errorstr);
    			sr.startListening(srintent);
    		}
    	}
    	
    	public void onResults(Bundle results) {
    		//statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.redbuttonround));
    		ArrayList<String> data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
            
    		if (data.size() > 0) {
    			statustv.setText("Most likely result:" + data.get(0));
        		for (int i = 0; i < data.size(); i++) Log.d(TAG, "SpeechResult[" + i + "]: " + data.get(i));
    			checkresults(data);
    		}

    		sr.stopListening();
    		if (gameisrunning) sr.startListening(srintent);
    	}
             
    	public void onPartialResults(Bundle partialResults) {
    		Log.d(TAG, "onPartialResults");
    	}
            
    	public void onEvent(int eventType, Bundle params) {
    		Log.d(TAG, "onEvent " + eventType);
    	}
    }

	private void loadPrefs() {
		if (isFirstRun()) {
     		Log.v(TAG,"Prefs loading failed, suspect first run, initialising prefs..");
     		initprefs();
     		//phrases = default_phrases;
     	}
		int phraseCount = mPrefs.getInt("phraseCount", 0);
		phrases = new String[phraseCount];
		//TODO: FIXTHIS: MAYBE: matched = new Boolean[phraseCount];
		for (int i=0; i < phraseCount ; i++) {
			phrases[i] = mPrefs.getString("phrase" + i, "ERROR_LOADING_PREF");
			matched[i] = mPrefs.getBoolean("matched" + i, false);
		}
	}
    /* returns true if this is the first run */
    public boolean isFirstRun() {
    	return mPrefs.getBoolean("firstRun", true);
    }
        
    /* commits first run preferences */
    public void initprefs() {
    	default_phrases = getResources().getStringArray(R.array.default_phrases);
    	SharedPreferences.Editor edit = mPrefs.edit();
    	edit.clear();

    	for(int i = 0; i < default_phrases.length; i++) {
    		edit.putString("phrase" + i, default_phrases[i]);
    		edit.putBoolean("matched" + i, false);
    	}
    	edit.putInt("phraseCount", default_phrases.length);

    	edit.putBoolean("firstRun", false);
    	edit.commit();
    }
    
    
    protected void onDestroy() {
        super.onDestroy();
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_layout, menu);
        return true;
    }
    
    /** Handle Option menu item selection */
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_btn1:
        	startActivity(new Intent(this, ConfigScreen.class));
        	return true;
        case R.id.quit:
        	//tidy();
        	finish();
           	return true;
        }
        return false;
    }
    
    public void startgame() {
    	if (amOnline()) {
    		gameisrunning = true;
            
            StartStopButton.setText(getResources().getString(R.string.stop_button));
    		sr.startListening(srintent);
    	} else {
    		String s = getResources().getString(R.string.no_internet);
    		statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.redbuttonround));
    		statustv.setText(s);
    		Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show(); 
    		Log.v(TAG,"ERROR: No Internet connection detected");
    		stopgame();
    	}
    }
    
    public void stopgame() {
		gameisrunning = false;
        StartStopButton.setText(getResources().getString(R.string.start_button));
        sr.stopListening();
        statusButton.setBackgroundDrawable(getResources().getDrawable(R.layout.bluebuttonround));
        statustv.setText("Game Stopped. Not Listening.");
    }
    
    public void resetgame() {
    	//TODO: Something here
    }
    
    public void onClick(View v) {
    	switch(v.getId()) {
    	case R.id.btn_startstop:
    		if (gameisrunning) {
    			stopgame();
    		} else {
    			startgame();
       		}
    		break;
        }
    }

    
    public boolean amOnline() {
    	ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    	NetworkInfo info=cm.getActiveNetworkInfo();
    	cm = null; //Allow GC to reclaim
    	return (info != null && info.isConnected());
    }


    private void checkresults(ArrayList<String> results) {
    	for(Iterator<String> i = results.iterator(); i.hasNext();) {
    		Object o = i.next(); 
    		for(int x = 0; x < mAdapter.getCount();x++) {
    			TextView v = mAdapter.getItem(x);
    			if (v==null) { 
    				// This shouldn't happen
    				Log.v(TAG, "ERROR: got a null tv");
    				continue;
    			}

    			String y = (String) v.getText();
    			if(o.toString().toUpperCase().indexOf(y.toUpperCase()) != -1) {
    				// Matched Word/Phrase!
    				mAdapter.highlightInGreen(x);
    			}
    		}
    		//Log.v(TAG,"Received: " + o.toString());
    	}
    }
    
    @Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}
    
    public class myAdapter extends BaseAdapter {
    	//private Context myContext;
    	private TextView[] myCells;
    	
    	
    	public myAdapter(Context c) {
    		//myContext = c;
        	myCells = new TextView[phrases.length];
        	
        	for (int i = 0; i < getCount(); i++) {
        		matched[i]=false;
        	}
        }

		@Override
		public int getCount() {
			return myCells.length;
			//return default_phrases.length;
		}

		@Override
		public TextView getItem(int position) {
			 TextView cell = (TextView) mGrid.getChildAt(position);
			 return cell;
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v;
			if (convertView == null) {  // if it's not recycled, initialise the gridview
		        LayoutInflater inflater = getLayoutInflater();
		        v = inflater.inflate(R.layout.gridview, null);
			} else {
	            v = convertView;
	        }

			TextView tv = (TextView) v.findViewById(R.id.gvTextView);
			tv.setText(phrases[position]);
			return v;
		}
    	
		public void highlightInGreen(int position) {
			  TextView cell;
			  cell = (TextView) mGrid.getChildAt(position);
			  if (cell != null) {
				  if (!matched[position]) {
					  cell.setTextColor(GREEN_INT);
					  matched[position]=true;
					  Toast.makeText(getApplicationContext(), String.valueOf(mAdapter.getMatchedCount()) + "/" + String.valueOf(mAdapter.getCount()), Toast.LENGTH_SHORT).show();
					  notifyDataSetChanged();
				  }
			  } else {
				  Log.v(TAG,"ERROR: GOT A NULL TextView position passed to highlightInGreen()");
			  }
		}
		
		public int getMatchedCount() {
			int count=0;
			for(int x = 0; x < matched.length; x++) {
				if (matched[x]) count++;
			}
			return count;
		}
    }
}

